<?php

/**
 *  库存更新管理
 * @copyright   Copyright (c) 2006 - 2010 DZH 友拓软件友拓通
 * @category   	库存信息
 * @package  	Model
 * @author    	黄明兴
 * @version 	2.1,2012-07-22
*/

class StoragePublicModel extends Model {
	/// 定义表名
	protected $tableName = 'storage';
	/// 参数包括$_POST $_GET
	private $params 		= array();
	/// 库存规格，属性
	private $storage_attr 	= array();
	/// 定义各流程对应有type值
	private $relation_type	= array(
						'loadContainer'		=> 1,
						'instock'			=> 2,
						'saleOrder'			=> 3,
						'adjust'			=> 4,
						'returnSaleOrder' 	=> 5,
						'transfer' 			=> 6,
						'delivery'			=> 7,
						'initStorage'		=> 8,
						'profitandloss'		=> 9,
						
	);
	/// 当前库存更新的流程名称
	private $module_name = '';
	
	/**
	 * 更新库存公共接口
	 *
	 * @param  参数 $params
	 * @param  方法名称，默认取模块名称，首字母转小写
	 * @return  null
	 */
	public function updateStorage($params,$method_name=null){
		$this->_module = $params['_module'];
		$this->_action = $params['_action'];
		empty($method_name) && $method_name = ucwords_first($this->_module);
		$this->module_name = $method_name;
		$this->params = $params;
		$this->getSpec();
		$this->$method_name();
	}
	
	/**
	 * 根据配置信息获取库存更新属性
	 *
	 * @return  null
	 */
	private function getSpec(){
		static $storage_attr;
		if($storage_attr) {
			$this->storage_attr = $storage_attr;
		}else {
			// 声明固定项，仓库,产品，可销售库存是不存在仓库对应代码会出现 0 as warehouse_id 务必不可修改$storage_attr中warehouse_id索引顺序
			$storage_attr = array('warehouse_id','product_id');
			if (C('storage_format')>=2) {
				$storage_attr[] = 'capability';
			}
			if (C('storage_format')>=3) {
				$storage_attr[] = 'dozen';
			}
			if (C('storage_color')) {
				$storage_attr[] = 'color_id';
			}
			if (C('storage_size')) {
				$storage_attr[] = 'size_id';
			}
			if (C('storage_mantissa')) {
				$storage_attr[] = 'mantissa';
			}
			$this->storage_attr = $storage_attr;
		}
	}
	
	/**
	 * 根据规格生成查询条件
	 * @param  array
	 * @param  int  1实际库存 2可销售库存
	 * @return  string
	 */
	private function getSpecWhere($value,$type){
		$where = array();
		foreach ($this->storage_attr as $spec_field) {
			if($type==2 && $spec_field=='warehouse_id'){continue;}
			$where[] = $spec_field.'='.$value[$spec_field];
		}
		return implode(' and ',$where);
	}
	
	
	/**
	 * 装柜更新库存
	 *
	 * @return  bool
	 */
	private function loadContainer(){
		if (C('loadContainer.sale_storage')!=1) return true;
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		// 暂存集装箱或已入库时直接删除旧库存
		if ($this->params['load_state']>=2) {
			$sql = 'select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=1 and main_id='.$this->params['id'];
		}else {
			$sql = 'select quantity,id as detail_id,0 as '.$str_field.' from load_container_details where load_container_id='.$this->params['id'].'  
					union all 
					select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=1 and main_id='.$this->params['id'];
		}
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$storage_log_var = $value;
			$storage_log_var['main_id'] 		= $this->params['id'];
			$storage_log_var['relation_type'] 	= $this->relation_type[$this->module_name];
			M('StorageLog')->add($storage_log_var);
			$this->execSaleStorage($value);
		}
		return true;
	}
	
	
	/**
	 * 入库更新库存
	 * 
	 * @return  bool
	 */
	private function instock(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity,id as detail_id,'.$str_field.' from instock_detail where instock_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=2 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execSaleStorage($value);
			$this->execRealStorage($value);
		}
		return true;
	}
	
	/**
	 * 销售更新库存
	 * 
	 * @return  bool
	 */
	private function saleOrder(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity*-1 as quantity,id as detail_id,'.$str_field.' from sale_order_detail where sale_order_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=3 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execSaleStorage($value);
			if(C('sale.relation_sale_follow_up')!=1) $this->execRealStorage($value);
		}
		return true;
	}
	
	
	/**
	 * 发货更新库存
	 * 
	 * @return  bool
	 */
	private function delivery(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity*-1 as quantity,id as detail_id,'.$str_field.' from delivery_detail where delivery_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=7 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execRealStorage($value);
		}
		/// 销售单完成时由于实际发货与销售可能出现不一致情况，此处还原销售单扣除的可销售库存，按实际发货扣除。
		if ((C('delivery.multi_delivery')==2 || (C('delivery.multi_delivery')==1 && $this->params['sale_finish']==1)) && ACTION_NAME!='delete') {
			$temp = M('delivery_detail')->field('sale_order_id')->where('delivery_id='.$this->params['id'])->find();
			$sale_order_id = $temp['sale_order_id'];
			if($sale_order_id<=0){
				$temp = M('delivery_detail_del')->field('sale_order_id')->where('delivery_id='.$this->params['id'])->find();
				$sale_order_id = $temp['sale_order_id'];
			}
			/// 先还原上次扣除的不一致库存，再根据发货单与销售单差异更新可销售库存
			$sql = 'select quantity*-1 as quantity,relation_type,detail_id,'.$str_field.' from storage_log where relation_type=10 and main_id='.$sale_order_id.' 
				union all select quantity as quantity,3 as realtion_type,id as detail_id,0 as '.$str_field.' from sale_order_detail where sale_order_id='.$sale_order_id.'  
				union all select quantity*-1 as quantity,7 as realtion_type,id as detail_id,0 as '.$str_field.' from delivery_detail where sale_order_id='.$sale_order_id;
		$sql = 'select sum(quantity) as quantity,10 as relation_type,'.$sale_order_id.' as main_id,detail_id,'.$str_field.' from ('.$sql.') as tmp group by '.$str_field.' having sum(quantity)!=0';
			$var = $this->db->query($sql);
			foreach ((array)$var as $value) {
				$this->execStorageLog($value,true);
				unset($value['main_id'],$value['relation_type']);
				$this->execSaleStorage($value);
			}
		}else {
			$temp = M('delivery_detail')->field('sale_order_id')->where('delivery_id='.$this->params['id'])->find();
			$sale_order_id = $temp['sale_order_id'];
			if($sale_order_id<=0){
				$temp = M('delivery_detail_del')->field('sale_order_id')->where('delivery_id='.$this->params['id'])->find();
				$sale_order_id = $temp['sale_order_id'];
			}
			$sql = 'select sum(quantity*-1) as quantity,relation_type,main_id,detail_id,'.$str_field.' from storage_log where relation_type=10 and main_id='.$sale_order_id.' group by main_id,relation_type,'.$str_field.' having sum(quantity)!=0';
			$var = $this->db->query($sql);
			foreach ((array)$var as $value) {
				$this->execStorageLog($value,true);
				unset($value['main_id'],$value['relation_type']);
				$this->execSaleStorage($value);
			}
		}
		return true;
	}
	
	
	/**
	 * 退换货更新库存
	 * 
	 * @return  bool
	 */
	private function returnSaleOrder(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity,id as detail_id,'.$str_field.' from return_sale_order_detail where is_use=1 and return_sale_order_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=5 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		/// 查询是否存在对应换货单
		$temp = M('return_sale_order')->field('sale_order_id')->find($this->params['id']);
		if(is_array($var)) {
			foreach ($var as $value) {
				$this->execStorageLog($value);
				$this->execSaleStorage($value);
				$this->execRealStorage($value);
			}
		}
		return true;
	}
	
	/**
	 * 调整更新库存
	 * 
	 * @return  bool
	 */
	private function adjust(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity,id as detail_id,'.$str_field.' from adjust_detail where adjust_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=4 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execSaleStorage($value);
			$this->execRealStorage($value);
			
		}
		return true;
	}
	
	/**
	 * 盈亏更新库存
	 * 
	 * @return  bool
	 */
	private function profitandloss(){
		// 盈亏只在过帐才更新且不可执行其它操作
		if (ACTION_NAME!='update') {return true;}
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select (stocktake_quantity-storage_quantity) as quantity,a.id as detail_id,'.$str_field.' from profitandloss_detail a left join profitandloss b on(a.profitandloss_id=b.id) where a.profitandloss_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=9 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execSaleStorage($value);
			$this->execRealStorage($value);
		}
		return true;
	}
	
	/**
	 * 调拨更新库存
	 * 
	 * @return  bool
	 */
	private function transfer(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity*-1 as quantity,id as detail_id,'.$str_field.' from transfer_detail where transfer_id='.$this->params['id'].'  
				union all 
				select quantity,id as detail_id,in_warehouse_id as '.$str_field.' from transfer_detail where transfer_id='.$this->params['id'].' 
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=6 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execSaleStorage($value);
			$this->execRealStorage($value);
		}
		return true;
	}
	
	/**
	 * 期初更新库存
	 * 
	 * @return  bool
	 */
	private function initStorage(){
		$ary_field = $this->storage_attr;
		$str_field = implode(',',$ary_field);
		$sql = 'select quantity,b.id as detail_id,'.$str_field.' from init_storage_detail a left join init_storage b on(a.init_storage_id=b.id) where init_storage_id='.$this->params['id'].'  
				union all 
				select quantity*-1 as quantity,detail_id,'.$str_field.' from storage_log where relation_type=8 and main_id='.$this->params['id'];
		$sql = 'select sum(quantity) as quantity,detail_id,'.$str_field.' from ('.$sql.') as tmp group by detail_id,'.$str_field.' having sum(quantity)!=0';
		$var = $this->db->query($sql);
		foreach ((array)$var as $value) {
			$this->execStorageLog($value);
			$this->execSaleStorage($value);
			$this->execRealStorage($value);
			
		}
		return true;
	}
	
	/**
	 * 添加库存日志
	 *
	 * @param  array $value
	 * @param  bool $flag true 直接入库  false 补充日志信息
	 * @return gbool
	 */
	private function execStorageLog($value,$flag=false){
		if ($flag===false) {
			$value['main_id'] 		= $this->params['id'];
			$value['relation_type'] = $this->relation_type[$this->module_name];
		}
		if(!M('StorageLog')->add($value)){
			throw_json('库存更新失败，库存日志异常，请立即联系客服人员！');
		}
	}
	
	/**
	 * 更新可销售库存
	 *
	 * @param  array $value
	 * @return  bool
	 */
	private function execSaleStorage($value){
		$rs = '';
		unset($value['detail_id']);
		$where = $this->getSpecWhere($value,2);
		$count = M('SaleStorage')->where($where)->count();
		if ($count==0) {
			M('SaleStorage')->add($value);
		}elseif ($count==1){
			$rs = M('SaleStorage')->where($where)->find();
			M('SaleStorage')->where($where)->save(array('quantity'=>$rs['quantity']+$value['quantity']));
		}elseif($count>1){
			throw_json('库存更新失败，同规格存在多条记录，请立即联系客服人员！');
		}
	}
	
	/**
	 * 更新实际库存
	 *
	 * @param  array $value
	 * @return  bool
	 */
	private function execRealStorage($value){
		$rs = '';
		unset($value['detail_id']);
		$where = $this->getSpecWhere($value,1);
		$count = M('Storage')->where($where)->count();
		if ($count==0) {
			M('Storage')->add($value);
		}elseif ($count==1){
			$rs = M('Storage')->where($where)->find();
			M('Storage')->where($where)->save(array('quantity'=>$rs['quantity']+$value['quantity']));
		}elseif($count>1){
			throw_json('库存更新失败，同规格存在多条记录，请立即联系客服人员！');
		}
	}
}